package lfp.addressselector.widget;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Point;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;

import java.util.ArrayList;

import lfp.addressselector.R;
import lfp.addressselector.bean.PathData;
import lfp.addressselector.svgparser.SVGReader;
import lfp.addressselector.util.LogUtil;
import lfp.addressselector.util.StringFormat;

/**
 * Created by Administrator on 2017/6/6.
 */

public class MapsView extends View implements SVGReader.IReaderFinish {


//    /**
//     * 这个flag标记是否为多点触摸操作
//     */
//    public static final int FLAG_MULTI_POINT_TOUCH = 0x2;


    public MapsView(Context context) {
        this(context, null);
    }

    public MapsView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MapsView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }


    public static int mMapViewFlag;
    public TouchHelper mTouchHelper = new TouchHelper() {
        @Override
        public void onClick(int x, int y) {
            LogUtil.getLogger().e(StringFormat.Format("down:[{0},{1}]", x, y));
        }

        @Override
        public void onMove(int x, int y, int dx, int dy) {
//            if (mTouchHelper.isMagnify()) {

            mTranslate_X += dx;
            mTranslate_Y += dy;
            postInvalidate();
//            }
        }

//        @Override
//        public void onMove(int x, int y) {
//            if (mTouchHelper.isMagnify()) { //放大之后才能移动地图
//                LogUtil.getLogger().e(StringFormat.Format("move>>[{0},{1}]", x, y));
//
//            }
//        }

        @Override
        public void onScale(Point center, double scale) {
            LogUtil.getLogger().e(StringFormat.Format("scale - [{0},{1}] - {2}", center.x, center.y, scale));
            postInvalidate();
        }
    };

    final float mMeasureRatio = 0.7352036f;//View尺寸自适应比例
    Matrix mMatrix;
    SVGReader mSVGRader;
    float mZoomRatio; //svg大小自适应View
    Paint mPaint;
    ArrayList<PathData> mMapDatas;

    public void recycle() {
        mSVGRader.recycle();
    }

    void init() {
        mSVGRader = new SVGReader(getContext());
        mSVGRader.setIReaderFinish(this);
        mSVGRader.reader(R.raw.chinahigh);
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mTouchHelper.init(getContext());
        mMatrix = new Matrix();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int with = MeasureSpec.getSize(widthMeasureSpec);
        setMeasuredDimension(with, (int) (mMeasureRatio * with));
        int offset = getOffSet();
        mTranslate_X = offset;
        mTranslate_Y = offset;
    }


    int mTranslate_X, mTranslate_Y;

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (mMapDatas != null) {
            canvas.save();
//            canvas.drawColor(Color.YELLOW);
//            canvas.saveLayer(null, null, Canvas.CLIP_SAVE_FLAG);;
            float scale = mZoomRatio * (float) mTouchHelper.getZoomScale();
            canvas.scale(scale, scale);


            canvas.translate(mTranslate_X, mTranslate_Y);

//            Point point = mTouchHelper.getZoomCenterPoint();
//            if (point != null) canvas.translate(-point.x, -point.y);

//            mMatrix.reset();
//            mMatrix.postScale(scale, scale);
//            mMatrix.postTranslate(offset, offset);
//            mMatrix.setScale(scale, scale);
//            mMatrix.setTranslate(mTouchHelper.getTouchMoveOffsetX(), mTouchHelper.getTouchMoveOffsetY());
//            Point zoomCenterPoint = mTouchHelper.getZoomCenterPoint();
//            if (zoomCenterPoint != null)
//                mMatrix.preTranslate(-zoomCenterPoint.x * scale + offset, -zoomCenterPoint.y * scale + offset);
//            canvas.setMatrix(mMatrix);

            for (PathData path : mMapDatas) {
                path.onDraw(canvas, mPaint, false);
            }
            canvas.restore();
        }

    }


    @Override
    public void onReaderFinish(ArrayList<PathData> mPathDatas, SVGReader.MapBouns mMapBouns) {
        mMapDatas = mPathDatas;
        computeMapScale(mMapBouns);
        postInvalidate();
    }

    //计算Map缩放比例，以自适应View的大小
    void computeMapScale(SVGReader.MapBouns mMapBouns) {
        int offset = getOffSet() * 2;
        float widthZoomRatio = (getWidth() - offset) / mMapBouns.getWidth();
        float heightZoomRatio = (getHeight() - offset) / mMapBouns.getHeight();
        mZoomRatio = Math.min(widthZoomRatio, heightZoomRatio);
    }

    //偏移量
    int getOffSet() {
        return Math.max(getPaddingTop(), Math.max(getPaddingRight(), Math.max(getPaddingLeft(), getPaddingBottom())));
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return mTouchHelper.onTouchEvent(event);
    }


    //触摸事件处理
    private abstract static class TouchHelper {
        // 最小和最大缩放的规模 [0] < [1]
        public static double[] mZoomScaleLimit = new double[]{0.9f, 2f};

        /**
         * 单移动点位置变化
         */
        public static final int FLAG_TOUCH_MOVE_CHANGE = 0x1;
        /**
         * 多移动点位置变化
         */
        public static final int FLAG_MULTI_TOUCH_MOVE_CHANGE = 0x2;
        /**
         * 拦截单点点击事件
         */
        public static final int FLAG_INTERCEPT_TOUCH_EVENT = 0x4;

        /**
         * 标记一个触摸点弹起来了 - 用于处理多余的触摸点弹出后重置移动位移
         */
        public static final int FLAG_ACTION_POINTER_UP = 0x8;


        int mTouchHelperFlag;
        ViewConfiguration mViewConfiguration;
        int mTouchDown_X;
        int mTouchDown_Y;
        int mTouchMove_X;
        int mTouchMove_Y;

        double mTwoMultiDistance_Down; //点下时两点距离
        double mTwoMultiDistance_Move; //移动时两点距离
        int mTouchMulti_1_Down_X;
        int mTouchMulti_1_Down_Y;
        int mTouchMulti_1_Move_X;
        int mTouchMulti_1_Move_Y;
        int mTouchMulti_2_Down_X;
        int mTouchMulti_2_Down_Y;
        int mTouchMulti_2_Move_X;
        int mTouchMulti_2_Move_Y;

        Point mMultiTouchCenterPoint = new Point(); //缩放中心点
        double mZoomScale = 1; //缩放比例

        void checkZoomScaleLimit() {
            if (mZoomScaleLimit.length < 2)
                throw new SecurityException("Due to the (mZoomScaleLimit.length < 2)");
            if (mZoomScaleLimit[0] > mZoomScaleLimit[1])
                throw new SecurityException("Due to the (mZoomScaleLimit[0]>mZoomScaleLimit[1])");
            if (mZoomScaleLimit[0] > 1 || mZoomScaleLimit[1] < 1)
                throw new SecurityException("Due to the (mZoomScaleLimit[0] >= 1 || mZoomScaleLimit[1] < 1)");
        }

        void checkZoomScale() {
            if (mZoomScale < mZoomScaleLimit[0])
                throw new SecurityException("Due to the (mZoomScale< mZoomScaleLimit[0])");
            if (mZoomScale > mZoomScaleLimit[1])
                throw new SecurityException("Due to the (mZoomScale>mZoomScaleLimit[0])");
        }

        public void init(Context mContext) {
            mViewConfiguration = ViewConfiguration.get(mContext);
        }

        //设置缩放比例限制
        public void setZoomScaleLimit(double[] limit) {
            mZoomScaleLimit = limit;
            checkZoomScaleLimit();
        }

        //用来计算位移的临时变量
        int mTouchMoveOffset_x;
        int mTouchMoveOffset_y;

        public void setTouchDown(int x1, int y1) {
            mTouchDown_X = x1;
            mTouchDown_Y = y1;
            mTouchHelperFlag &= ~FLAG_INTERCEPT_TOUCH_EVENT;

            mTouchMove_X = x1;
            mTouchMove_Y = y1;
        }

        public void setTouchMove(int x1, int y1) {
            if (mTouchMove_X == x1 && mTouchMove_Y == y1) {
                mTouchHelperFlag &= ~FLAG_TOUCH_MOVE_CHANGE;
            } else {
                if ((mMapViewFlag & FLAG_ACTION_POINTER_UP) != 0) {
                    mTouchMoveOffset_x = 0;
                    mTouchMoveOffset_y = 0;
                    mMapViewFlag &= ~FLAG_ACTION_POINTER_UP;
                } else {
                    mTouchMoveOffset_x = x1 - mTouchMove_X;
                    mTouchMoveOffset_y = y1 - mTouchMove_Y;
                }

                mTouchHelperFlag |= FLAG_TOUCH_MOVE_CHANGE;
                mTouchMove_X = x1;
                mTouchMove_Y = y1;
                if (getTowPointDistance(mTouchMove_X, mTouchMove_Y, mTouchDown_X, mTouchDown_Y) > mViewConfiguration.getScaledTouchSlop()) { //如果当前事件滑动了，那么他就不是一个点击事件
                    mTouchHelperFlag |= FLAG_INTERCEPT_TOUCH_EVENT;
                }
            }
        }

        //记录两个触摸点点下时的信息
        public void setTouchMulti_Down(int x1, int y1, int x2, int y2) {
            mTouchMulti_1_Down_X = x1;
            mTouchMulti_1_Down_Y = y1;
            mTouchMulti_2_Down_X = x2;
            mTouchMulti_2_Down_Y = y2;
            mTwoMultiDistance_Down = getTowPointDistance(x1, y1, x2, y2);
            mTwoMultiDistance_Move = 0; //清空上一次事件的值
            mMultiTouchCenterPoint.set((x1 + x2) / 2, (y1 + y2) / 2);
        }

        //记录两个触摸点移动时的信息
        public void setTouchMulti_Move(int x1, int y1, int x2, int y2) {
            if (mTouchMulti_1_Move_X == x1 && mTouchMulti_1_Move_Y == y1 && mTouchMulti_2_Move_X == x2 && mTouchMulti_2_Move_Y == y2) {
                mTouchHelperFlag &= ~FLAG_MULTI_TOUCH_MOVE_CHANGE;
            } else {
                double distance = getTowPointDistance(x1, y1, x2, y2);
                if (Math.abs(distance - mTwoMultiDistance_Move) < 2) { //未达到缩放的最小位移
//                    LogUtil.getLogger().e(StringFormat.Format("{0}未到达位移要求：{1}", Math.abs(distance - mTwoMultiDistance_Move), mViewConfiguration.getScaledTouchSlop()));
                    mTouchHelperFlag &= ~FLAG_MULTI_TOUCH_MOVE_CHANGE;
                    return;
                }
                mTouchHelperFlag |= FLAG_INTERCEPT_TOUCH_EVENT;
                mTouchHelperFlag |= FLAG_MULTI_TOUCH_MOVE_CHANGE;

                boolean isChange = false;
                double ratio = (distance / mTwoMultiDistance_Down - 1) / 10 + 1; //缩放比例 <1 缩放》1
                double actualRatio = mZoomScale * ratio;
//                LogUtil.getLogger().e("actualRatio:" + actualRatio);
                if (actualRatio < mZoomScaleLimit[0]) actualRatio = mZoomScaleLimit[0];
                else if (actualRatio > mZoomScaleLimit[1]) actualRatio = mZoomScaleLimit[1];
                if (mZoomScale != actualRatio) {
                    mZoomScale = actualRatio;
                    isChange = true;
                }
                checkZoomScale();


                if (isChange) {
                    mTouchMulti_1_Move_X = x1;
                    mTouchMulti_1_Move_Y = y1;
                    mTouchMulti_2_Move_X = x2;
                    mTouchMulti_2_Move_Y = y2;
                    mTwoMultiDistance_Move = distance;
                } else {
                    mTouchHelperFlag &= ~FLAG_MULTI_TOUCH_MOVE_CHANGE;
                }
            }
        }

        //获得两点距离
        public double getTowPointDistance(double x1, double y1, double x2, double y2) {
            int xlen = Math.abs((int) x1 - (int) x2);
            int ylen = Math.abs((int) y1 - (int) y2);
            return Math.sqrt((double) xlen * xlen + (double) ylen * ylen);
        }

        //返回多点手势改变
        public boolean isChangeMulti() {
            return (mTouchHelperFlag & FLAG_MULTI_TOUCH_MOVE_CHANGE) != 0;
        }

        //返回单点手势改变
        public boolean isChange() {
            return (mTouchHelperFlag & FLAG_TOUCH_MOVE_CHANGE) != 0;
        }

        //是否拦截单点点击事件
        public boolean isInterceptTouchEvent() {
            return (mTouchHelperFlag & FLAG_INTERCEPT_TOUCH_EVENT) != 0;
        }

        //获得缩放中心点位置
        public Point getZoomCenterPoint() {
            return mMultiTouchCenterPoint;
        }

        //获得点击位置
        public Point getTouchDown() {
            if (mTouchMove_X == 0 && mTouchMove_Y == 0) {
                return new Point(mTouchDown_X, mTouchDown_Y);
            } else return new Point(mTouchMove_X, mTouchMove_Y);
        }

        //是否缩放
        public boolean isZoom() {
            return mZoomScale >= mZoomScaleLimit[0] && mZoomScale <= mZoomScaleLimit[1] && mZoomScale != 1;
        }

        //是否放大
        public boolean isMagnify() {
            return mZoomScale > 1 && mZoomScale <= mZoomScaleLimit[1];
        }


        //获得缩放比例
        public double getZoomScale() {
            return mZoomScale;
        }

        public void reset() {
            mZoomScale = 0;
            mTouchHelperFlag &= ~FLAG_TOUCH_MOVE_CHANGE;
            mTouchHelperFlag &= ~FLAG_MULTI_TOUCH_MOVE_CHANGE;
            mTouchHelperFlag &= ~FLAG_INTERCEPT_TOUCH_EVENT;


            mTouchDown_X = 0;
            mTouchDown_Y = 0;
            mTouchMove_X = 0;
            mTouchMove_Y = 0;

            mTwoMultiDistance_Down = 0; //点下时两点距离
            mTwoMultiDistance_Move = 0; //移动时两点距离
            mTouchMulti_1_Down_X = 0;
            mTouchMulti_1_Down_Y = 0;
            mTouchMulti_1_Move_X = 0;
            mTouchMulti_1_Move_Y = 0;
            mTouchMulti_2_Down_X = 0;
            mTouchMulti_2_Down_Y = 0;
            mTouchMulti_2_Move_X = 0;
            mTouchMulti_2_Move_Y = 0;
            mZoomScale = 1; //缩放比例
        }

        /**
         * 当点击了某个点
         *
         * @param x 点击位置
         * @param y 点击位置
         */
        public abstract void onClick(int x, int y);


        /**
         * 当移动了地图
         *
         * @param x 移动点位置
         * @param y 移动点位置
         */
        public abstract void onMove(int x, int y, int dx, int dy);

        /**
         * 当缩放的时候
         *
         * @param center 缩放原点
         * @param scale  缩放比例
         */
        public abstract void onScale(Point center, double scale);


        //触摸时间处理
        public boolean onTouchEvent(MotionEvent event) {
            int action = event.getAction();
            int nTouchCount = event.getPointerCount(); // 触摸点数目
            if (nTouchCount == 1) {
                switch (action) {
                    case MotionEvent.ACTION_DOWN:
                        setTouchDown((int) event.getX(), (int) event.getY());
//                    LogUtil.getLogger().e("1 >>> ACTION_DOWN");
                        break;
                    case MotionEvent.ACTION_MOVE:
                        setTouchMove((int) event.getX(), (int) event.getY());
                        if (isChange()) {
//                        LogUtil.getLogger().e("1 >>> ACTION_MOVE");
                            onMove(mTouchMove_X, mTouchMove_Y, mTouchMoveOffset_x, mTouchMoveOffset_y);
                        }
                        break;
                    case MotionEvent.ACTION_UP:
                        if (isInterceptTouchEvent()) { //由于本次事件被多点触摸使用掉了，这里做单点点击事件的一些重置动作


                        } else {
//                        LogUtil.getLogger().e("1 >>> ACTION_UP");
                            Point mTouchPoint = getTouchDown(); //获得当前点击的位置
                            onClick(mTouchPoint.x, mTouchPoint.y);
                        }
                        break;
                    default:
                        LogUtil.getLogger().e("1 >>> " + action);
                        break;
                }
            } else if (nTouchCount >= 2) {
                //多点触控 会堵塞单点触摸动作，直到多个触摸点抬起到只剩下一个触摸点的时候，会将事件还给单点触摸进行处理
                //所以在上面单点触摸中 增加了一个 FLAG_INTERCEPT_TOUCH_EVENT 状态用来标识这次事件已被多点触摸处理了
                int Mask = action & MotionEvent.ACTION_MASK;
                if (Mask == MotionEvent.ACTION_POINTER_DOWN) {
//                LogUtil.getLogger().e("2 >>> ACTION_POINTER_DOWN");
                    setTouchMulti_Down((int) event.getX(0), (int) event.getY(0), (int) event.getX(1), (int) event.getY(1));
                } else if (action == MotionEvent.ACTION_MOVE) {
                    setTouchMulti_Move((int) event.getX(0), (int) event.getY(0), (int) event.getX(1), (int) event.getY(1));
                    if (isChangeMulti()) {
//                    LogUtil.getLogger().e("2 >>> ACTION_MOVE");
                        onScale(mMultiTouchCenterPoint, getZoomScale());
                    }
                } else if (Mask == MotionEvent.ACTION_POINTER_UP) { //抬起
                    mMapViewFlag |= FLAG_ACTION_POINTER_UP;
                }
            }
//        return super.onTouchEvent(event);
            return true;
        }
    }

}
